# GerikSpellsPieMenuSelectScreen.py
# This is the screen used to draw the pie-menu targets.
# It should not need to be modified, as it draws it's important use
# through the GSPieMenuGraphicsPolicy functions.
#

# gReloaded is used to determine when a python file reset has occured.
# After a python reaload, any time the screen tries to update, it will
# kill the screen. This is done because many times a screen will
# still be up and trying to update, which will cause problems because
# often global variables have not been reinitialized yet. Afterwards,
# gReloaded is set back to false.
gReloaded = True

from CvPythonExtensions import *
import CvUtil

import ScreenInput
import CvScreensInterface
import GerikSpellsInterface

# globals
gc = CyGlobalContext()
ArtFileMgr = CyArtFileMgr()

class GerikSpellsPieMenuSelectScreen:

    ##########################################
    # __init__
    ##########################################
    def __init__(self):
        self.pScreen = None
        self.m_pGraphicsPolicy = None
        self.m_pTargetList = []

        # The spot where the mouse is when the screen is created, assumingly centered on the plot in question
        self.iCenterX = 0
        self.iCenterY = 0

        # Size of the bars
        # GERIKESTODO
        self.iBarHeight = 12
        self.iBarSpacing = 6

         # The current "page" that is going to be shown
        self.page = 0

        # The number of targets on the longest page. Necessary so that pages with fewer targets can be sure
        # not to show old targets that may stay on the screen when switched away from that full page.
        self.iSizeLargestPage = 0

        # The number of bars on the target that has more bars than others. Necessary so that when that target
        # is no longer visible, we have a number that we know that no target has more bars than, so we can just
        # assume that any target had these many bars when erasing them.
        self.iMostBarsOnTargetLastUpdate = 0

        # The name that is checked for to see if they pressed the turn page button.
        self.szTurnPageFunctionName = "BobSeger"

        self.totalTargets = 0
        self.szTargetChooserPrefix = "GerikSpellsPieMenuSelect"

        # If the menu is animated when loading, this value will start 0.0 and move up to 1.0. The sizes and placements the
        # buttons will depend upon this value.
        self.fAnimationPercent = 0.0

        # If the menu is animated, this value will be used to update the above percent value during the update.
        self.fAnimationIncrement = 5

        self.m_bCancelOnNextUpdate = False

    ##########################################
    # Interface Screen
    ##########################################
    def interfaceScreen(self, pGraphicsPolicy, pTargetList):
        # If the screen was not up when the last python reload
        # happened, then gReloaded will be True until update, which
        # will be during a valid screen. This will stop that.
        global gReloaded
        gReloaded = False
        
        self.m_pGraphicsPolicy = pGraphicsPolicy
        self.m_pTargetList = pTargetList

        if (not self.m_pTargetList or len(self.m_pTargetList) == 0):
            CvUtil.pyPrint("Warning: Targetted spell cancelled due to no targets")
            CvUtil.pyPrint("Current spell: %d" % GerikSpellsInterface.getCurrentSpellValue())
            GerikSpellsInterface.cancelSpell()
            GerikSpellsInterface.resetLocalInterfaceMode()
            return

        self.page = 0
        self.iSizeLargestPage = 0
        for pageList in self.m_pTargetList:
            if len(pageList) > self.iSizeLargestPage:
                self.iSizeLargestPage = len(pageList)

        self.fAnimationPercent = 0.0
            
        self.pScreen = CyGInterfaceScreen( GerikSpellsInterface.getPieMenuSelectScreenName(), GerikSpellsInterface.getPieMenuSelectScreenEnum() )

        # Get the mouse position
        pMousePos = CyInterface().getMousePos()

        self.iCenterX = pMousePos.x
        self.iCenterY = pMousePos.y - 20 # In my experience, the menu always seems lower than expected. This raises it a little.

        iResX = self.pScreen.getXResolution()
        iResY = self.pScreen.getYResolution()

        self.pScreen.setDimensions(0,0, iResX, iResY)

        # Handle Input is only called if there is something to catch the input.
        # Make a huge, invisible checkbox to "catch" the input.
        self.pScreen.addCheckBoxGFC("CatchAllWidget", "Art/Interface/Buttons/empty.dds", "Art/Interface/Buttons/empty.dds",
                                    0, 0, iResX, iResY, WidgetTypes.WIDGET_GENERAL, 0, -1, ButtonStyles.BUTTON_STYLE_LABEL)
                                                      
        # Although we do need to close when the user hits escape, disable it so we can
        # do some cleanup activities ourselves in handleInput if necessary.
        self.pScreen.setCloseOnEscape(False)

        self.pScreen.showScreen(PopupStates.POPUPSTATE_IMMEDIATE, True)

        self.m_bCancelOnNextUpdate = False

    def hideScreen(self):
        if (self.pScreen):
            self.pScreen.hideScreen()
            self.pScreen = None
            


    ##########################################
    # handleInput
    ##########################################
    def handleInput(self, inputClass):
        # They pressed escape, so cancel the spell casting
        if (inputClass.getNotifyCode() == int(NotifyCode.NOTIFY_CHARACTER) and
            inputClass.getData() == int(InputTypes.KB_ESCAPE)):
            GerikSpellsInterface.cancelSpell()

        # They right-clicked, so cancel the spell casting
        if (inputClass.getNotifyCode() == int(NotifyCode.NOTIFY_CLICKED) and
            inputClass.getFlags() & MouseFlags.MOUSE_RBUTTONUP):
            GerikSpellsInterface.cancelSpell()

        if (inputClass.getNotifyCode() == int(NotifyCode.NOTIFY_CLICKED) and
            inputClass.getFlags() & MouseFlags.MOUSE_LBUTTONUP):
            # Turn the Page
            if (inputClass.getFunctionName() == self.szTurnPageFunctionName):
                self.page = (self.page + 1) % len(self.m_pTargetList)
                self.updateView()

            # Get the target selected:
            if (inputClass.getFunctionName() == self.szTargetChooserPrefix):
                self.m_pGraphicsPolicy.targetSelected(self.m_pTargetList[inputClass.getData1()][inputClass.getData2()])
        
    def mouseOverPlot(self):
        pass

    def stop(self, bCancel):
        if (bCancel):
            self.m_bCancelOnNextUpdate = bCancel
        else:
            self.hideScreen()

    ##########################################
    # update
    ##########################################
    def update(self, fDelta):
        global gReloaded
        if (gReloaded):
            screenToKill = CyGInterfaceScreen( GerikSpellsInterface.getPieMenuSelectScreenName(), GerikSpellsInterface.getPieMenuSelectScreenEnum() )
            screenToKill.hideScreen()
            gReloaded = False
            return

        if (self.m_bCancelOnNextUpdate):
            self.hideScreen()
            self.m_bCancelOnNextUpdate = False
            GerikSpellsInterface.resetLocalInterfaceMode()
            
        # Update the animation. If there was some animation done, redraw the screen
        if (self.updatePopupAnimation(fDelta)):
            self.updateView()

        


    ##########################################
    # Updates
    ##########################################
    
    """
    Updates the percentage that the menu is animated. Until the animation is finished, this will return true.
    """
    def updatePopupAnimation(self, fDelta):
        if (self.fAnimationPercent >= 1.0):
            return False
        else:
            self.fAnimationPercent += self.fAnimationIncrement * fDelta
            return True

    """
    Redraws all of the targes and bars, as well as removing those that aren't going to be used any more
    """
    def updateView(self):
        # pageList is the list of all targets that need to be displayed.
        pageList = self.m_pTargetList[self.page]
        iPageLen = len(pageList)

        iMostBarsOnTarget = 0

        # For every target that must be drawn...
        for iI in range(0, iPageLen):

            # Re-add the check box button. Using the same name every time, these "added" check boxes actually replace the old ones
            # that we drew last update.
            szString = "%s%d" % (self.szTargetChooserPrefix, iI)
            pData = pageList[iI]

            # Get the info from the spell class.
            szButtonName = pData.getButton()
            iCenterOffsetX, iCenterOffsetY, iButtonSizeX, iButtonSizeY = self.m_pGraphicsPolicy.getTargetButtonDimensions(iI, iPageLen, self.fAnimationPercent)

            # Used to make the center offset adhere to the middle of the button, not to the left of it
            iCenterOffsetX -= (iButtonSizeX / 2)

            # Actually add the widget to the screen.
            szBackground = "%s%s" % (szString, "BG")
            self.pScreen.addDDSGFC(szBackground, "Art/Interface/buttons/disablebutton.dds",
                                    self.iCenterX + iCenterOffsetX, self.iCenterY + iCenterOffsetY,
                                    iButtonSizeX, iButtonSizeY,
                                    WidgetTypes.WIDGET_GENERAL, -1, -1)
            self.pScreen.addCheckBoxGFC( szString, szButtonName,
                                        ArtFileMgr.getInterfaceArtInfo("BUTTON_HILITE_SQUARE").getPath(),
                                        self.iCenterX + iCenterOffsetX, self.iCenterY + iCenterOffsetY,
                                        iButtonSizeX, iButtonSizeY,
                                        WidgetTypes.WIDGET_GERIK_SPELLS_TARGET_INFO,
                                        self.page, iI, # For use in getting popup info.
                                        ButtonStyles.BUTTON_STYLE_LABEL )


            # Tell the screen to show this widget when it's drawing.
            self.pScreen.show(szBackground)
            self.pScreen.show(szString)

            # Disable or enable the target.
            self.pScreen.enable(szString, pData.isTargettable(GerikSpellsInterface.getCurrentSpell().getCastingGroup(), GerikSpellsInterface.getCurrentSpell().getCastingPlot(), pData.getTarget(), False) )

            # Get the list of bars from the spell class.
            barsList = pData.getBars()
            iNumBars = 0
            if (barsList):
                iNumBars = len(barsList)

            # Make sure to keep track of the largest amount of bars on any target.
            if (iNumBars > iMostBarsOnTarget):
                iMostBarsOnTarget = iNumBars
            
            # For every bar tuple we have, make a new bar.
            iBarSizeY = iButtonSizeY / 4
            for iJ in range(0, iNumBars):
                    szStringBar = szString + ("Bars%d" % iJ)
                    self.pScreen.addStackedBarGFC( szStringBar,
                                              # Place just below the button
                                              self.iCenterX + iCenterOffsetX, self.iCenterY + iCenterOffsetY + (iButtonSizeY * 4 / 5) + ((iBarSizeY / 3) * iJ),
                                              iButtonSizeX, iBarSizeY,
                                              InfoBarTypes.NUM_INFOBAR_TYPES, WidgetTypes.WIDGET_GENERAL,
                                              self.page, iI # For use in getting target info
                                              ) 
                    self.pScreen.setBarPercentage( szStringBar, InfoBarTypes.INFOBAR_STORED, float(barsList[iJ][0]) / float(barsList[iJ][1]) )
                    self.pScreen.setStackedBarColors(szStringBar, InfoBarTypes.INFOBAR_STORED, gc.getInfoTypeForString(barsList[iJ][2]))
                    self.pScreen.show( szStringBar )

            # If we created less bars on this target than last time, the extra bars will still be shown during this update.
            # Be sure to hide them from view
            for iJ in range(iNumBars, self.iMostBarsOnTargetLastUpdate):
                szStringBar = szString + ("Bars%d" % iJ)
                self.pScreen.hide(szStringBar)

        # End of for loop to draw buttons and bars.
        # Remove any targets no longer in use, including their bars.
        for iI in range(len(pageList), self.iSizeLargestPage):
            szString = "%s%d" % (self.szTargetChooserPrefix, iI)
            self.pScreen.hide(szString)
            self.pScreen.hide("%s%s" % (szString, "BG"))
            for iJ in range(0, self.iMostBarsOnTargetLastUpdate):
                szStringBar = szString + ("Bars%d" % iJ)
                self.pScreen.hide(szStringBar)


        # Update the max number of bars on screen, gathered while drawing all the bars.
        # This will be used during the next update to determine the max number of bars
        # any one target will have.
        self.iMostBarsOnTargetLastUpdate = iMostBarsOnTarget

        # If there is more than one page of units, draw the middle "turn page" button.
        if (len(self.m_pTargetList) > 1):
            iCenterOffsetX, iCenterOffsetY, iSizeX, iSizeY = self.m_pGraphicsPolicy.getTurnPageButtonDimensions(self.fAnimationPercent)

            # Used to make the center offset adhere to the middle of the button, not to the upper-left of it
            iCenterOffsetX -= (iButtonSizeX / 2)

            self.pScreen.addCheckBoxGFC(self.szTurnPageFunctionName, gc.getMissionInfo(gc.getInfoTypeForString("MISSION_SKIP")).getButton(),
                                        ArtFileMgr.getInterfaceArtInfo("BUTTON_HILITE_SQUARE").getPath(),
                                        self.iCenterX + iCenterOffsetX, self.iCenterY + iCenterOffsetY,
                                        iSizeX, iSizeY,
                                        WidgetTypes.WIDGET_GENERAL, -1, -1, ButtonStyles.BUTTON_STYLE_LABEL )

        
        

